package com.shsoft.utils;

import android.bluetooth.BluetoothGatt;
import android.graphics.Color;
import android.os.Build;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.RequiresApi;

import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleGattCallback;
import com.clj.fastble.callback.BleReadCallback;
import com.clj.fastble.callback.BleScanCallback;
import com.clj.fastble.callback.BleWriteCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.clj.fastble.scan.BleScanRuleConfig;
import com.hb.dialog.dialog.LoadingDialog;
import com.shsoft.colorfulcc.MainActivity;
import com.shsoft.common.AppManager;
import com.shsoft.common.Constant;
import com.shsoft.common.MyApplication;

import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 蓝牙工具类
 */
public class BleUtil {
    private BleDevice device;
    private LoadingDialog loadingDialog;
    private Timer timer;
    private TimerTask timerTask;
    private TextView tips;
    private MainActivity activity;

    public BleUtil(TextView tips, MainActivity activity) {
        this.tips = tips;
        this.activity = activity;
        this.loadingDialog = new LoadingDialog(activity);
        this.loadingDialog.setMessage("请稍等");
        this.loadingDialog.setCancelable(false);
    }

    // 蓝牙初始化
    public void bleInit(MyApplication app){
        BleManager.getInstance()
                .enableLog(true)
                .setReConnectCount(2, 5000) // 设置重连次数
                .setConnectOverTime(10000) // 设置连接超时时间，单位毫秒
                .setOperateTimeout(5000)  // 设置操作超时时间，单位毫秒
                .init(app);
        // 判断设备是否支持蓝牙
        if(!BleManager.getInstance().isSupportBle()){ // 不支持蓝牙
            Toast.makeText(app,"抱歉，该设备不支持蓝牙",Toast.LENGTH_LONG).show();
            AppManager.finishAllActivity();
        }
    }

    // 连接蓝牙设备
    public void connectBLE(){
        tips.setText(" (正在连接设备) ");
        tips.setTextColor(Color.BLUE);
        loadingDialog.show();
        // 配置扫描规则
        BleScanRuleConfig scanRuleConfig = new BleScanRuleConfig.Builder()
                .setDeviceName(true, Constant.BLE_NAME)  // 只扫描指定的服务的设备
                .setAutoConnect(true).build();
        BleManager.getInstance().initScanRule(scanRuleConfig);
        // 开启扫描
        BleManager.getInstance().scan(new BleScanCallback() {
            @Override
            public void onScanStarted(boolean success) {
                MessageUtil.logDebug("开始扫描");
                tips.setText(" (正在扫描设备) ");
                tips.setTextColor(Color.BLUE);
                tips.setClickable(false);
            }
            @Override
            public void onLeScan(BleDevice bleDevice) {
            }
            @Override
            public void onScanning(BleDevice bleDevice) {
                device = bleDevice;
            }
            @Override
            public void onScanFinished(List<BleDevice> scanResultList) {
                MessageUtil.logDebug("扫描结束");
                if(device != null){
                    // 连接设备
                    BleManager.getInstance().connect(device, new BleGattCallback() {
                        @Override
                        public void onStartConnect() {
                            MessageUtil.logDebug("开始连接");
                            tips.setText(" (正在连接设备) ");
                            tips.setTextColor(Color.BLUE);
                            tips.setClickable(false);
                        }
                        @Override
                        public void onConnectFail(BleDevice bleDevice, BleException exception) {
                            MessageUtil.logDebug("连接失败...");
                            loadingDialog.dismiss();
                            tips.setText(" (连接失败，点击重连) ");
                            tips.setTextColor(Color.RED);
                            tips.setClickable(true);
                        }
                        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
                        @Override
                        public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
                            MessageUtil.logDebug("连接成功");
                            loadingDialog.dismiss();
                            tips.setText(" (连接成功) ");
                            tips.setTextColor(Color.BLUE);
                            tips.setClickable(false);
                            // 连接成功后，开始每隔一秒检查一次I2C设备情况
                            startCheckI2cDevice();
                        }
                        @Override
                        public void onDisConnected(boolean isActiveDisConnected, BleDevice bleDevice, BluetoothGatt gatt, int status) {
                            MessageUtil.logDebug("连接断开");
                            tips.setText(" (连接断开，点击重连) ");
                            tips.setTextColor(Color.RED);
                            tips.setClickable(true);
                            // 断开后，也停止每秒检查一次I2C设备的操作
                            timer.cancel();
                            timerTask.cancel();
                        }
                    });
                }else {
                    MessageUtil.logDebug("未发现设备");
                    loadingDialog.dismiss();
                    tips.setText(" (未发现设备，点击重连) ");
                    tips.setTextColor(Color.RED);
                    tips.setClickable(true);
                }
            }
        });
    }

    // 连接成功后，开始每隔一秒检查一次I2C设备情况
    private void startCheckI2cDevice(){
        timer = new Timer();
        timerTask = new TimerTask() {
            @Override
            public void run() {
                readI2cOnline();
            }
        };
        timer.schedule(timerTask,0,1000);
    }

    // 读取设备在线离线的特征值
    public void readI2cOnline(){
        BleManager.getInstance().read(device, Constant.SERVICE_UUID, Constant.I2C_ONLINE_CHARACTERISTIC_UUID, new BleReadCallback() {
            @Override
            public void onReadSuccess(byte[] data) {
                // 读特征值数据成功
//                MessageUtil.logDebug("读取I2c设备状态成功");
                String status = new String(data);
//                MessageUtil.logDebug(status);
                if(status.equals(Constant.I2C_OFFLINE)){
                    tips.setText(" (灯板连接异常，请检查) ");
                    tips.setTextColor(Color.RED);
                }else {
                    tips.setText(" (连接成功) ");
                    tips.setTextColor(Color.BLUE);
                }
            }
            @Override
            public void onReadFailure(BleException exception) {
                // 读特征值数据失败
//                MessageUtil.logDebug("读取I2c设备状态失败");
            }
        });
    }

    // 读取传送结果
    public void readTransferResult(){
        loadingDialog.show();
        BleManager.getInstance().read(device, Constant.SERVICE_UUID, Constant.TRANSFER_RESULT_CHARACTERISTIC_UUID, new BleReadCallback() {
            @Override
            public void onReadSuccess(byte[] data) {
                // 读特征值数据成功
                String info = new String(data);
                MessageUtil.logDebug(info);
                loadingDialog.dismiss();
                if(info.equals("success")){
                    MessageUtil.toastShort(activity, "发送数据成功");
                }else {
                    MessageUtil.toastShort(activity, "发送数据失败，请检查灯板连接");
                }
            }
            @Override
            public void onReadFailure(BleException exception) {
                // 读特征值数据失败
                loadingDialog.dismiss();
                MessageUtil.logDebug("读取传送结果失败");
                MessageUtil.toastShort(activity, "读取传送结果失败，请检查设备连接");
            }
        });
    }


    // 向设备写入新的灯珠显示信息
    public void writeNewInfo(){
        loadingDialog.show();
        // 将灯珠显示信息编码成字节数组
        byte[] data = DataUtil.getData(activity);
        MessageUtil.logDebug(new String(data));
        // 通过蓝牙发送
        BleManager.getInstance().write(device, Constant.SERVICE_UUID, Constant.I2C_NEW_INFO_CHARACTERISTIC_UUID, data, new BleWriteCallback() {
            @Override
            public void onWriteSuccess(int current, int total, byte[] justWrite) {
                // 发送数据到设备成功（分包发送的情况下，可以通过方法中返回的参数可以查看发送进度）
                if(current == total){ // 所有包都发送完成
                    // 所有分包都发送完成后，去传送结果的特征值里读取结果
                    readTransferResult();
                }
            }
            @Override
            public void onWriteFailure(BleException exception) {
                // 发送数据到设备失败
                loadingDialog.dismiss();
                MessageUtil.toastShort(activity,"发送数据失败,请检查连接");
            }
        });
    }
}
